<?php

defined('SYSPATH') or die('Access error!');

/**
 * model 基类 
 */
abstract class Model
{

    protected $db;
    protected $table;
    protected $id = 'id';
    public $rules;
    public $validate;
    private $order_str;

    public static function factory($table, $db = NULL)
    {
        $class = 'Model_' . $table;
        return new $class($db, $table);
    }

    public function __construct($db = NULL, $table = '')
    {
        if ($db)
        {
            $this->db = $db;
        }
        elseif (!$this->db)
        {
            $this->db = Database::$default;
        }

        if (is_string($this->db))
        {
            $this->db = Database::instance($this->db);
        }

        $this->table = $this->db->get_table($table);
    }

    /**
     * 判断表中某字段是否重复，若重复则中止程序，并给出错误信息
     *
     * @access  public
     * @param   string  $col    字段名
     * @param   string  $name   字段值
     * @param   integer $id
     *
     * @return void
     */
    function is_exist($params, $id = 0, $where = '')
    {
        $current_col = $this->get_where($params);

        $sql = 'SELECT COUNT(*) FROM ' . $this->table . " WHERE " . $current_col;
        $sql .= empty($id) ? '' : ' AND ' . $this->id . " <> '$id'";
        $sql .= empty($where) ? '' : ' AND ' . $where;
        return $this->db->get_var($sql) != 0;
    }

    public function get_fun_rows()
    {
        return $this->db->num_rows;
    }

    /**
     *  根据条件得到一条数据
     * @param type $conditions  条件
     * @param string $params     所要返回的值
     * @return type
     */
    public function get_row($conditions, $params = '')
    {
        $where = $this->get_where($conditions);
        if ($params == '')
        {
            $params = '*';
        }
        $sql = "SELECT " . $params . " FROM " . $this->table . " WHERE " . $where;
        $data = $this->db->get_row($sql);
        if (count($data) > 0)
        {
            return $data;
        }

        return array();
    }

    /**
     *  根据某个条件 得到所需要的字段值
     * @param type $condition
     * @param type $param
     * @return type
     */
    public function get_var($conditions, $param)
    {
        $where = $this->get_where($conditions);
        $sql = "SELECT $param" . " FROM " . $this->table . " WHERE " . $where;
        $param = $this->db->get_var($sql);
        return !empty($param) ? $param : '';
    }

    /**
     *  根据所给的条件删除某条数据
     * @param type $condition
     * @return type
     */
    public function delete($condition)
    {
        $where = $this->get_where($condition);
        $sql = "DELETE FROM " . $this->table . " WHERE " . $where;
        return $this->db->query($sql);
    }

    public function get_col($condition, $param)
    {
        $where = $this->get_where($condition);
        $sql = "SELECT $param" . " FROM " . $this->table . " WHERE " . $where;
        $data = $this->db->get_col($sql);
        return $data;
    }

    /**
     *   有待于优化
     * 
     * @param type $where
     * @return type
     */
    public function get_results($where = '', $params = '*')
    {
        $sql = '';
        $sql .= "SELECT " . $params . " FROM " . $this->table;
        $sql .=!empty($where) ? " where 1=1  " . $where : '';
        $results_temp = $this->db->get_results($sql, ARRAY_A);
        $results = array();
        if (count($results_temp) > 0)
        {
            foreach ($results_temp as $key => $value)
            {
                $results[$key] = (array) $value;
            }
            return $results;
        }
        else
        {
            return array();
        }
    }

    /**
     *   有待于优化
     * 
     * @param type $where
     * @return type
     */
    public function get_results2($condition = '', $params = '*')
    {
        $where = $this->get_where($condition);

        if (empty($where))
        {
            $where = ' 1=1 ';
        }
        $sql = "SELECT " . $params . " FROM " . $this->table . ' WHERE ' . $where . " " . $this->order_str;
        
        $results_temp = $this->db->get_results($sql, ARRAY_A);
        $results = array();
        if (count($results_temp) > 0)
        {
            foreach ($results_temp as $key => $value)
            {
                $results[$key] = (array) $value;
            }
            return $results;
        }
        else
        {
            return array();
        }
    }

    public function order_by($order_arr, $table_rename = '')
    {
        $order_sql = " ORDER BY ";
        $table_rename = !empty($table_rename)?$table_rename.'.':'';

        $order_str = '';
        if (Arr::validate_arr($order_arr))
        {
            foreach ($order_arr as $key => $value)
            {
                $order_sql .= $table_rename . $key . " " . $value . ",";
            }
            $order_str = rtrim($order_sql, ',');
        }

        $this->order_str = $order_str;
        
        return $this->order_str;
    }

    /**
     *  简便的插入操作(单行)
     * 
     * @param type $table
     * @param type $data
     * @return boolean
     */
    public function insert($data = array(), $table = '')
    {
        $table = !empty($table) ? $table : $this->table;
        $params = $this->get_set($data);
        if ($this->db->query("INSERT " . $table . " SET " . $params))
        {
            return $this->db->insert_id;
        }
        else
        {
            return false;
        }
    }

    public function get_id()
    {
        return $this->db->insert_id;
    }

    /**
     * 简单的update操作
     * 
     * @param type $table
     * @param type $data
     * @param type $conditions
     * @return boolean
     */
    public function update($data = array(), $conditions = array(), $table = '')
    {

        if (empty($data))
        {
            return false;
        }

        $params = $this->get_set($data);

        if (!empty($conditions))
        {
            $condition = " WHERE " . $this->get_where($conditions);
        }
        else
        {
            $condition = '';
        }
        $sql = "UPDATE " . $this->table . " SET " . $params . $condition;
        if ($return_val = $this->db->query($sql))
        {
            return $return_val;
        }
        return false;
    }

    public function update_operate_num($string, $conditions)
    {
        if (!empty($conditions))
        {
            $condition = " WHERE " . $this->get_where($conditions);
        }
        else
        {
            $condition = '';
        }
        if ($return_val = $this->db->query("UPDATE " . $this->table . " SET " . $string . $condition))
        {
            return $return_val;
        }
        return false;
    }

    /**
     *  得到sql的条件语句
     * @param type $params
     * @return type
     */
    public function get_where($params)
    {
        if (is_array($params))
        {
            $in_num = array_keys($params);
            if (is_array($params[$in_num[0]]) && count($in_num) > 1)
            {
                $in_str = $this->get_in($params[$in_num[0]], $in_num[0]);
                unset($params[$in_num[0]]);
                $and_str = $this->get_and($params);
                return $in_str . ' AND ' . $and_str;
            }
            elseif (is_array($params[$in_num[0]]))
            {
                return $this->get_in($params[$in_num[0]], $in_num[0]);
            }
            else
            {
                return $this->get_and($params);
            }
        }
        else
        {
            return $params;
        }
    }

    /**
     * 创建in条件语句 "IN('a','b')";
     *
     * @access   public
     * @param    mix      $item_list      列表数组或字符串
     * @param    string   $field_name     字段名称
     *
     * @return   void
     */
    function get_in($item_list, $field_name = '')
    {
        if (empty($item_list))
        {
            return $field_name . " IN ('') ";
        }
        else
        {
            if (!is_array($item_list))
            {
                $item_list = explode(',', $item_list);
            }
            $item_list = array_unique($item_list);
            $item_list_tmp = '';
            foreach ($item_list AS $item)
            {
                if ($item !== '')
                {
                    $item_list_tmp .= $item_list_tmp ? ",'$item'" : "'$item'";
                }
            }
            if (empty($item_list_tmp))
            {
                return $field_name . " IN ('') ";
            }
            else
            {
                return $field_name . ' IN (' . $item_list_tmp . ') ';
            }
        }
    }

    /**
     *  创建and条件 例如  name='lxd' and 'age'=>26
     * @param type $params
     * @return type
     */
    function get_and($params)
    {
        $sql = '';
        foreach ($params as $field => $val)
        {
            if ($val === 'true')
                $val = 1;
            if ($val === 'false')
                $val = 0;

            if (is_numeric($val))
            {
                $val = $this->db->escape($val);
                $sql .= "$field=" . $val . " AND ";
            }
            else
            {
                $val = $this->db->escape($val);
                $field_arr = explode('.', $field);
                $field_pre = '';
                if (count($field_arr) > 1)
                {
                    $field = $field_arr[1];
                    $field_pre = $field_arr[0].'.';
                }

                if ($field == 'name' || $field == 'title' || $field == 'username')
                {
                    $sql .= $field_pre."$field LIKE '%" . $val . "%' AND ";
                }
                else
                {
                    $val = "'" . $val . "'";
                    $sql .= $field_pre."$field=" . $val . " AND ";
                }
            }
        }

        return substr($sql, 0, -4);
    }

    function get_set($parms)
    {
        $sql = '';
        foreach ($parms as $field => $val)
        {
            if ($val === 'true')
                $val = 1;
            if ($val === 'false')
                $val = 0;

            if ($val == 'NOW()')
            {
                $sql .= "$field = " . $this->db->escape($val) . ", ";
            }
            else
            {
                $sql .= "$field = '" . $this->db->escape($val) . "', ";
            }
        }

        return substr($sql, 0, -2);
    }

    public function get_table_where($table_rename, $params)
    {
        $where_sql = '';
        if (is_array($params))
        {
            $temp = array();
            foreach ($params as $key => $value)
            {
                $temp[$table_rename . '.' . $key] = $value;
            }
            if (Arr::validate_arr($temp))
            {
                $where_sql = ' WHERE ' . $this->get_where($temp);
            }
        }


        return $where_sql;
    }

    /**
     *  根据分类的id获取
     * @param type $id
     * @return type
     */
    public function get_related_category($id)
    {
        $related_category = Model_Category::factory('category')->get_category_list('parent_id=' . $id);
        return count($related_category) > 0 ? $related_category : array();
    }

    /**
     *  根据给的from和and得到数量
     * @param type $from_sql
     * @param type $and_sql
     * @return type
     */
    public function get_page_count($sql)
    {
        $total = $this->db->get_results($sql);
        return count($total);
    }

    /**
     *  根据sql和分页条件获取数据列表
     * @param type $sql
     * @param type $page_count
     * @return type
     */
    public function get_page_list($sql, $page_count)
    {
        $data = array();
        $pagination = Pagination::instance();
        $current_sql = $sql . ' LIMIT ' . (($pagination->get_page() - 1) * $page_count) . ', ' . $page_count;
        $data['list'] = (array) $this->db->get_results($current_sql, ARRAY_A);
        $data['total'] = $this->get_page_count($sql);
        $pagination->records($data['total']);
        $pagination->records_per_page($page_count);
        $data['page'] = $pagination->render();
        return $data;
    }

    public function validate($data)
    {
        $this->validate = Validate::factory($data);
        if (count($this->rules) > 0)
        {
            foreach ($this->rules as $field => $rule)
            {
                $field = ($field === 1) ? TRUE : $field;
                $this->validate->rules($field, $rule);
            }

            return $this->validate->check();
        }
        return TRUE;
    }

}
